package org.gdstash.ui;

import org.gdstash.util.GDImagePool;
import org.gdstash.util.GDLog;
import org.gdstash.util.GDMsgFormatter;

import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemListener;
import java.awt.event.WindowEvent;
import java.util.List;

public class GDLogDialog extends JDialog {
    private JLabel lblMessage;
    private JButton btnOk;
    private GDIconCheckBox cbSuccess;
    private GDIconCheckBox cbInfo;
    private GDIconCheckBox cbWarning;
    private GDIconCheckBox cbError;
    private GDLogTableModel model;
    private JTable table;

    public GDLogDialog(final Frame owner, final String message, final GDLog.MessageType type, final GDLog log) {
        super(owner, true);
        this.adjustUI();
        GroupLayout layout = null;
        GroupLayout.SequentialGroup hGroup = null;
        GroupLayout.SequentialGroup vGroup = null;
        final JPanel panel = this.buildFilterPanel();
        Icon icon = null;
        if (type == GDLog.MessageType.Success) {
            icon = GDImagePool.iconMsgSuccess32;
        }
        if (type == GDLog.MessageType.Info) {
            icon = GDImagePool.iconMsgInfo32;
        }
        if (type == GDLog.MessageType.Warning) {
            icon = GDImagePool.iconMsgWarning32;
        }
        if (type == GDLog.MessageType.Error) {
            icon = GDImagePool.iconMsgError32;
        }
        this.lblMessage = new JLabel(message, icon, 0);
        this.btnOk.addActionListener(new OkActionListener());
        this.model = new GDLogTableModel(log);
        (this.table = new JTable(this.model)).setRowHeight(18);
        this.table.getColumnModel().getColumn(0).setPreferredWidth(40);
        this.table.getColumnModel().getColumn(1).setPreferredWidth(400);
        this.table.setAutoResizeMode(3);
        final JScrollPane scroll = new JScrollPane(this.table);
        scroll.getVerticalScrollBar().setUnitIncrement(2 * GDStashFrame.iniConfig.sectUI.fontSize);
        layout = new GroupLayout(this.getContentPane());
        this.getContentPane().setLayout(layout);
        layout.setAutoCreateGaps(true);
        layout.setAutoCreateContainerGaps(true);
        hGroup = layout.createSequentialGroup();
        hGroup.addGroup(layout.createParallelGroup().addComponent(this.lblMessage).addComponent(this.btnOk).addComponent(panel).addComponent(scroll));
        layout.setHorizontalGroup(hGroup);
        vGroup = layout.createSequentialGroup();
        vGroup.addGroup(layout.createParallelGroup().addComponent(this.lblMessage)).addGroup(layout.createParallelGroup().addComponent(this.btnOk)).addGroup(layout.createParallelGroup().addComponent(panel)).addGroup(layout.createParallelGroup().addComponent(scroll));
        layout.setVerticalGroup(vGroup);
        layout.linkSize(0, this.lblMessage, this.btnOk);
        layout.linkSize(0, this.lblMessage, panel);
        layout.linkSize(1, this.lblMessage, this.btnOk);
        this.setDefaultCloseOperation(2);
        this.pack();
        this.setLocationRelativeTo(owner);
        this.setVisible(true);
    }

    public void adjustUI() {
        Font fntLabel = UIManager.getDefaults().getFont("Label.font");
        Font fntButton = UIManager.getDefaults().getFont("Button.font");
        if (fntButton == null) {
            fntButton = fntLabel;
        }
        Font fntTable = UIManager.getDefaults().getFont("TableHeader.font");
        if (fntTable == null) {
            fntTable = fntLabel;
        }
        fntLabel = fntLabel.deriveFont((float) GDStashFrame.iniConfig.sectUI.fontSize);
        fntButton = fntButton.deriveFont((float) GDStashFrame.iniConfig.sectUI.fontSize);
        fntTable = fntTable.deriveFont((float) GDStashFrame.iniConfig.sectUI.fontSize);
        if (this.btnOk == null) {
            this.btnOk = new JButton();
        }
        this.btnOk.setText(GDMsgFormatter.getString(GDMsgFormatter.rbUI, "BTN_OK"));
        this.btnOk.setFont(fntButton);
        if (this.table != null) {
            this.table.getTableHeader().setFont(fntTable);
            this.table.setFont(fntLabel);
            final GDLogTableModel model = (GDLogTableModel) this.table.getModel();
            model.adjustUI();
        }
        if (this.cbSuccess == null) {
            (this.cbSuccess = new GDIconCheckBox(GDImagePool.iconMsgSuccess32, true)).addActionListener(new CheckboxActionListener());
        }
        if (this.cbInfo == null) {
            (this.cbInfo = new GDIconCheckBox(GDImagePool.iconMsgInfo32, true)).addActionListener(new CheckboxActionListener());
        }
        if (this.cbWarning == null) {
            (this.cbWarning = new GDIconCheckBox(GDImagePool.iconMsgWarning32, true)).addActionListener(new CheckboxActionListener());
        }
        if (this.cbError == null) {
            (this.cbError = new GDIconCheckBox(GDImagePool.iconMsgError32, true)).addActionListener(new CheckboxActionListener());
        }
    }

    private JPanel buildFilterPanel() {
        GroupLayout layout = null;
        GroupLayout.SequentialGroup hGroup = null;
        GroupLayout.SequentialGroup vGroup = null;
        final JPanel panel = new JPanel();
        layout = new GroupLayout(panel);
        panel.setLayout(layout);
        layout.setAutoCreateGaps(true);
        layout.setAutoCreateContainerGaps(true);
        hGroup = layout.createSequentialGroup();
        hGroup.addGroup(layout.createParallelGroup().addComponent(this.cbSuccess)).addGroup(layout.createParallelGroup().addComponent(this.cbInfo)).addGroup(layout.createParallelGroup().addComponent(this.cbWarning)).addGroup(layout.createParallelGroup().addComponent(this.cbError));
        layout.setHorizontalGroup(hGroup);
        vGroup = layout.createSequentialGroup();
        vGroup.addGroup(layout.createParallelGroup().addComponent(this.cbSuccess).addComponent(this.cbInfo).addComponent(this.cbWarning).addComponent(this.cbError));
        layout.setVerticalGroup(vGroup);
        layout.linkSize(0, this.cbSuccess, this.cbInfo);
        layout.linkSize(0, this.cbSuccess, this.cbWarning);
        layout.linkSize(0, this.cbSuccess, this.cbError);
        layout.linkSize(1, this.cbSuccess, this.cbInfo);
        layout.linkSize(1, this.cbSuccess, this.cbWarning);
        layout.linkSize(1, this.cbSuccess, this.cbError);
        return panel;
    }

    private static class GDLogTableModel extends DefaultTableModel {
        private static String[] columnNames;
        private GDLog.LogEntry[] entries;
        private String[] messages;
        private Icon[] icons;
        private int iSuccess;
        private int iInfo;
        private int iWarning;
        private int iError;

        public GDLogTableModel(final GDLog log) {
            final List<GDLog.LogEntry> list = log.getLog();
            this.adjustUI();
            this.entries = new GDLog.LogEntry[list.size()];
            this.iSuccess = 0;
            this.iInfo = 0;
            this.iWarning = 0;
            this.iError = 0;
            int i = 0;
            for (final GDLog.LogEntry entry : list) {
                if (entry.type == GDLog.MessageType.Success) {
                    ++this.iSuccess;
                }
                if (entry.type == GDLog.MessageType.Info) {
                    ++this.iInfo;
                }
                if (entry.type == GDLog.MessageType.Warning) {
                    ++this.iWarning;
                }
                if (entry.type == GDLog.MessageType.Error) {
                    ++this.iError;
                }
                this.entries[i] = entry;
                ++i;
            }
            this.filterMessages(true, true, true, true);
        }

        public void adjustUI() {
            if (GDLogTableModel.columnNames == null) {
                GDLogTableModel.columnNames = new String[2];
            }
            GDLogTableModel.columnNames[0] = GDMsgFormatter.getString(GDMsgFormatter.rbUI, "TXT_TYPE");
            GDLogTableModel.columnNames[1] = GDMsgFormatter.getString(GDMsgFormatter.rbUI, "TXT_MESSAGE");
            this.setColumnIdentifiers(GDLogTableModel.columnNames);
        }

        @Override
        public int getRowCount() {
            if (this.messages == null) {
                return 0;
            }
            return this.messages.length;
        }

        @Override
        public int getColumnCount() {
            return GDLogTableModel.columnNames.length;
        }

        @Override
        public String getColumnName(final int column) {
            return GDLogTableModel.columnNames[column];
        }

        @Override
        public Object getValueAt(final int row, final int column) {
            if (this.messages == null) {
                return null;
            }
            if (column == 0) {
                return this.icons[row];
            }
            if (column == 1) {
                return this.messages[row];
            }
            return null;
        }

        @Override
        public Class getColumnClass(final int column) {
            if (column == 0) {
                return Icon.class;
            }
            if (column == 1) {
                return String.class;
            }
            return Object.class;
        }

        public void filterMessages(final boolean success, final boolean info, final boolean warning, final boolean error) {
            int size = 0;
            if (success) {
                size += this.iSuccess;
            }
            if (info) {
                size += this.iInfo;
            }
            if (warning) {
                size += this.iWarning;
            }
            if (error) {
                size += this.iError;
            }
            if (size == 0) {
                this.messages = null;
                this.icons = null;
                this.fireTableDataChanged();
                return;
            }
            this.messages = new String[size];
            this.icons = new Icon[size];
            int count = 0;
            for (int i = 0; i < this.entries.length; ++i) {
                boolean match = false;
                Icon icon = null;
                if (success && this.entries[i].type == GDLog.MessageType.Success) {
                    match = true;
                    icon = GDImagePool.iconMsgSuccess16;
                }
                if (info && this.entries[i].type == GDLog.MessageType.Info) {
                    match = true;
                    icon = GDImagePool.iconMsgInfo16;
                }
                if (warning && this.entries[i].type == GDLog.MessageType.Warning) {
                    match = true;
                    icon = GDImagePool.iconMsgWarning16;
                }
                if (error && this.entries[i].type == GDLog.MessageType.Error) {
                    match = true;
                    icon = GDImagePool.iconMsgError16;
                }
                if (match) {
                    this.messages[count] = this.entries[i].str;
                    this.icons[count] = icon;
                    ++count;
                }
            }
            this.fireTableDataChanged();
        }

        static {
            GDLogTableModel.columnNames = null;
        }
    }

    private static class GDIconCheckBox extends JComponent {
        private JCheckBox checkbox;
        private JLabel label;

        public GDIconCheckBox(final Icon icon, final boolean selected) {
            (this.checkbox = new JCheckBox()).setSelected(selected);
            this.label = new JLabel(icon);
            GroupLayout layout = null;
            GroupLayout.SequentialGroup hGroup = null;
            GroupLayout.SequentialGroup vGroup = null;
            layout = new GroupLayout(this);
            this.setLayout(layout);
            layout.setAutoCreateGaps(true);
            layout.setAutoCreateContainerGaps(true);
            hGroup = layout.createSequentialGroup();
            hGroup.addGroup(layout.createParallelGroup().addComponent(this.checkbox)).addGroup(layout.createParallelGroup().addComponent(this.label));
            layout.setHorizontalGroup(hGroup);
            vGroup = layout.createSequentialGroup();
            vGroup.addGroup(layout.createParallelGroup().addComponent(this.checkbox).addComponent(this.label));
            layout.setVerticalGroup(vGroup);
            layout.linkSize(1, this.checkbox, this.label);
        }

        public void addActionListener(final ActionListener listener) {
            this.checkbox.addActionListener(listener);
        }

        public void addItemListener(final ItemListener listener) {
            this.checkbox.addItemListener(listener);
        }

        public void removeActionListener(final ActionListener listener) {
            this.checkbox.removeActionListener(listener);
        }

        public void removeItemListener(final ItemListener listener) {
            this.checkbox.removeItemListener(listener);
        }

        public boolean isSeleted() {
            return this.checkbox.isSelected();
        }

        public void setSelected(final boolean selected) {
            this.checkbox.setSelected(selected);
        }
    }

    private class CheckboxActionListener implements ActionListener {
        @Override
        public void actionPerformed(final ActionEvent e) {
            GDLogDialog.this.model.filterMessages(GDLogDialog.this.cbSuccess.isSeleted(), GDLogDialog.this.cbInfo.isSeleted(), GDLogDialog.this.cbWarning.isSeleted(), GDLogDialog.this.cbError.isSeleted());
        }
    }

    private class OkActionListener implements ActionListener {
        @Override
        public void actionPerformed(final ActionEvent e) {
            GDLogDialog.this.setVisible(false);
            GDLogDialog.this.dispatchEvent(new WindowEvent(GDLogDialog.this, 201));
        }
    }
}
